#pragma once
#include <typescommon.h>
#include <protocolParseCommon.h>
#include <commandBaseInform.h>
#include <hashCommandActuator.h>

// >0have data, ==0no data, < error
typedef int (*receiveRemoteDataCallback)(uint8_t *readbuffer, int readsize, void *userdata);
typedef int (*sendRemoteDataCallback)(const uint8_t *sendbuffer, int sendsize, void *userdata);
struct protocolCommandCommunicateInform
{
    // communicate receive data function
    receiveRemoteDataCallback receiveFunction;
    // communicate send data function
    sendRemoteDataCallback sendFunction;
    // communicate user data
    void *userdata;
    // my communicate addr.
    uint8_t my485Addr;

#if COMMAND_MASTER_CALL_DEFINE
    int8_t retryMaxTime;
    uint32_t commandWaitTimeoutMs;
#endif
    // OPTION
    // uint8_t crypteAesNormalKey[16];
    // uint8_t crypteAesNormalIV[16];
    // uint8_t crypteAesCommunicateKey[16];
    // uint8_t crypteAesCommunicateIV[16];
};
#define PROTOCOL_MAX_RETRY_NUMBER 5
#define PROTOCOL_MAX_WAIT_TIMEOUT_MS (60 * 1000)
#define PROTOCOL_MIN_WAIT_TIMEOUT_MS (50)

#define PROTOCOL_V2_COMMON_HEAD_SIZE (offsetof(struct protocolPackageCommonInform, pv2.v2Data))
#define PROTOCOL_COMMAND_COMMON_HEAD_SIZE (offsetof(struct commandCommonStruct, commandData))
#define PROTOCOL_V2_COMMAND_HEAD_SIZE (PROTOCOL_V2_COMMON_HEAD_SIZE + PROTOCOL_COMMAND_COMMON_HEAD_SIZE)
#define PROTOCOL_V2_COMMAND_DATA_SIZE (PROTOCOL_PACK_MAX_SIZE - PROTOCOL_V2_COMMAND_HEAD_SIZE)
#define PROTOCOL_V2_DATA_SIZE(usersize) (usersize + PROTOCOL_COMMAND_COMMON_HEAD_SIZE)

struct protocolProcessorInform
{
    // receive/send remote data callback, set by user
    struct protocolCommandCommunicateInform communicateInform;
    // parse receive data, and do command callback list,  set by user
    struct hashCommandActuatorManage protocolCommandMng;
    // parse receive data, protocol parser.
    struct protocolPackageParseInform parser;
    // for save parse data. used in mcu.
    char parsePackBuffer[PROTOCOL_PACK_MAX_SIZE];
#if COMMAND_MASTER_CALL_DEFINE
    // for master excute command and wait
    struct commandCommonStruct commandExcuter;
    uint8_t commandExcuterAddr;
#endif
};

void protocolProcessorInit(struct protocolProcessorInform *devider, struct protocolCommandCommunicateInform setCommuni,
                         struct hashCommandActuatorManage setHashActor);
uint16_t processerPackageProtocolData(struct protocolProcessorInform *processer, uint8_t *outpack, uint32_t outsize);
void protocolProcessorRunReceive(struct protocolProcessorInform *devider);
uint16_t protocolCommandPackAndSend(struct protocolProcessorInform *devider, uint8_t *outpack, uint32_t outsize);
#if COMMAND_MASTER_CALL_DEFINE
uint16_t generateCommandSerial();
int masterProcesserSetReTryCount(struct protocolProcessorInform *processer, uint8_t setRetry);
int masterProcesserSetTimeout(struct protocolProcessorInform *processer, uint32_t setTimeoutMs);
int masterCommandProcesserState(struct protocolProcessorInform *devider);
int masterCommandProcesserWaitResponse(struct protocolProcessorInform *devider);
int masterProcesserSendAndWaitResponse(struct protocolProcessorInform *processer, void *sendData, uint32_t sendSize);
#endif

